import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';

export interface I18nEntry {
    key: string;
    value: string;
    filePath: string;
    line: number;
}

export interface UntranslatedEntry {
    key: string;
    sourceFile: string;
    line: number;
}

export class I18nService {
    private cache: Map<string, I18nEntry> = new Map();
    private watcher: vscode.FileSystemWatcher | undefined;
    private translationFilePath: string = '';

    constructor() {
        this.initializeWatcher();
        this.loadTranslations();
    }

    private initializeWatcher() {
        const config = vscode.workspace.getConfiguration('i18nHelper');
        const i18nPath = config.get<string>('i18nPath', 'app/core/i18n');
        
        // Watch for changes in JSON files
        this.watcher = vscode.workspace.createFileSystemWatcher(
            new vscode.RelativePattern(
                vscode.workspace.workspaceFolders?.[0] || '',
                path.join(i18nPath, '*.json')
            )
        );

        // Update cache when files change
        this.watcher.onDidChange(() => this.loadTranslations());
        this.watcher.onDidCreate(() => this.loadTranslations());
        this.watcher.onDidDelete(() => this.loadTranslations());
    }

    public async reloadTranslations() {
        await this.loadTranslations();
    }

    private async loadTranslations() {
        this.cache.clear();
        const config = vscode.workspace.getConfiguration('i18nHelper');
        const i18nPath = config.get<string>('i18nPath', 'app/core/i18n');
        const defaultLanguage = config.get<string>('defaultLanguage', 'zh-CN');

        const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
        if (!workspaceFolder) {
            return;
        }

        this.translationFilePath = path.join(workspaceFolder.uri.fsPath, i18nPath, `${defaultLanguage}.json`);
        
        // Check if translation file exists
        if (!fs.existsSync(this.translationFilePath)) {
            vscode.window.showWarningMessage(`Translation file not found at: ${this.translationFilePath}`);
            return;
        }
        
        try {
            const content = await fs.promises.readFile(this.translationFilePath, 'utf-8');
            const translations = JSON.parse(content);
            
            // Read the file line by line to get line numbers
            const lines = content.split('\n');
            let lineNumber = 0;
            
            const processObject = (obj: any, prefix: string = '') => {
                for (const key of Object.keys(obj)) {
                    const fullKey = prefix ? `${prefix}.${key}` : key;
                    const value = obj[key];
                    
                    // Find the line number for this key
                    while (lineNumber < lines.length) {
                        if (lines[lineNumber].includes(`"${key}"`)) {
                            break;
                        }
                        lineNumber++;
                    }
                    
                    if (typeof value === 'string') {
                        this.cache.set(fullKey, {
                            key: fullKey,
                            value: value,
                            filePath: this.translationFilePath,
                            line: lineNumber
                        });
                    } else if (typeof value === 'object' && value !== null) {
                        processObject(value, fullKey);
                    }
                }
            };
            
            processObject(translations);
        } catch (error) {
            console.error('Failed to load translations:', error);
            vscode.window.showErrorMessage(`Failed to load translations: ${error}`);
        }
    }

    public getTranslation(key: string): I18nEntry | undefined {
        return this.cache.get(key);
    }

    public getAllTranslations(): I18nEntry[] {
        return Array.from(this.cache.values());
    }

    public isValidTranslationKey(key: string): boolean {
        return this.cache.has(key);
    }

    public getTranslationsByPrefix(prefix: string): I18nEntry[] {
        return Array.from(this.cache.values()).filter(
            entry => entry.key.startsWith(prefix)
        );
    }

    public dispose() {
        this.watcher?.dispose();
    }

    public async addTranslation(key: string, value: string): Promise<boolean> {
        try {
            if (!this.translationFilePath) {
                const config = vscode.workspace.getConfiguration('i18nHelper');
                const i18nPath = config.get<string>('i18nPath', 'app/core/i18n');
                const defaultLanguage = config.get<string>('defaultLanguage', 'zh-CN');
                const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
                
                if (!workspaceFolder) {
                    throw new Error('No workspace folder found');
                }
                
                this.translationFilePath = path.join(workspaceFolder.uri.fsPath, i18nPath, `${defaultLanguage}.json`);
            }

            // Read the current translations
            const content = await fs.promises.readFile(this.translationFilePath, 'utf-8');
            const translations = JSON.parse(content);

            // Split the key into parts and create nested structure
            const keyParts = key.split('.');
            let current = translations;
            
            // Create or traverse the nested structure
            for (let i = 0; i < keyParts.length - 1; i++) {
                const part = keyParts[i];
                if (!current[part]) {
                    current[part] = {};
                }
                current = current[part];
            }

            // Set the value at the final level
            const lastKey = keyParts[keyParts.length - 1];
            current[lastKey] = value;

            // Write back to file with proper formatting
            await fs.promises.writeFile(
                this.translationFilePath,
                JSON.stringify(translations, null, 4),
                'utf-8'
            );

            // Reload translations to update cache
            await this.loadTranslations();
            return true;
        } catch (error) {
            console.error('Failed to add translation:', error);
            vscode.window.showErrorMessage(`Failed to add translation: ${error}`);
            return false;
        }
    }

    public async scanForUntranslatedKeys(): Promise<UntranslatedEntry[]> {
        const untranslatedKeys: UntranslatedEntry[] = [];
        const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
        
        if (!workspaceFolder) {
            return [];
        }

        // Find all Python files in the workspace
        const files = await vscode.workspace.findFiles(
            '**/*.py',
            '**/node_modules/**'
        );

        const pattern = /t\(['"]([\w\.]+)['"]\)/g;

        for (const file of files) {
            const content = await fs.promises.readFile(file.fsPath, 'utf-8');
            const lines = content.split('\n');
            
            for (let i = 0; i < lines.length; i++) {
                const line = lines[i];
                const matches = Array.from(line.matchAll(pattern));
                
                for (const match of matches) {
                    const key = match[1];
                    if (!this.isValidTranslationKey(key)) {
                        untranslatedKeys.push({
                            key,
                            sourceFile: file.fsPath,
                            line: i + 1
                        });
                    }
                }
            }
        }

        // Remove duplicates based on key
        return Array.from(
            new Map(untranslatedKeys.map(item => [item.key, item])).values()
        );
    }

    public async batchAddTranslations(translations: Map<string, string>): Promise<boolean> {
        try {
            if (!this.translationFilePath) {
                const config = vscode.workspace.getConfiguration('i18nHelper');
                const i18nPath = config.get<string>('i18nPath', 'app/core/i18n');
                const defaultLanguage = config.get<string>('defaultLanguage', 'zh-CN');
                const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
                
                if (!workspaceFolder) {
                    throw new Error('No workspace folder found');
                }
                
                this.translationFilePath = path.join(workspaceFolder.uri.fsPath, i18nPath, `${defaultLanguage}.json`);
            }

            // Read the current translations
            const content = await fs.promises.readFile(this.translationFilePath, 'utf-8');
            const existingTranslations = JSON.parse(content);

            // Add new translations
            for (const [key, value] of translations.entries()) {
                const keyParts = key.split('.');
                let current = existingTranslations;
                
                // Create or traverse the nested structure
                for (let i = 0; i < keyParts.length - 1; i++) {
                    const part = keyParts[i];
                    if (!current[part]) {
                        current[part] = {};
                    }
                    current = current[part];
                }

                // Set the value at the final level
                const lastKey = keyParts[keyParts.length - 1];
                current[lastKey] = value;
            }

            // Write back to file with proper formatting
            await fs.promises.writeFile(
                this.translationFilePath,
                JSON.stringify(existingTranslations, null, 4),
                'utf-8'
            );

            // Reload translations to update cache
            await this.loadTranslations();
            return true;
        } catch (error) {
            console.error('Failed to batch add translations:', error);
            vscode.window.showErrorMessage(`Failed to batch add translations: ${error}`);
            return false;
        }
    }
} 